const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
const iconv = require('iconv-lite');

class VarsTreeItem extends vscode.TreeItem {
    /**
     * 
     * @param {{key:string, label:string, tooltip:string}} varType 
     * @param {vscode.TreeItemCollapsibleState} collapsibleState 
     */
    constructor(varType, collapsibleState = vscode.TreeItemCollapsibleState.None) {
        super(varType.label, collapsibleState);
        this.tooltip = varType.tooltip;
        this.key = varType.key
    }
}
/**
 * @implements {vscode.TreeDataProvider<ServerTreeItem>}
 */

class VarsUsedTreeViewProvider {

    /**
     * @type {Object.<string, string[]>}
     */
    vars = {}
    rules = [/(?<![A-Za-z0-9])[PDMNSIGAUTJZ]\d{1,3}(?![A-Za-z0-9])/gi]
    labels = {
        P: ["P0-P999 (私人变量，数字型)", "关闭对话框重置为0。"],
        D: ["D0-D999 (私人变量，数字型)", "下线不保存.摇筛子变量."],
        M: ["M0-M999 (私人变量，数字型)", "下线不保存.切换地图清空."],
        N: ["N0-N999 (私人变量，数字型)", "下线不保存.小退归0."],
        S: ["S0-S999 (私人变量，字符型)", "下线不保存.小退归0."],
        I: ["I0-I999 (全局变量，数字型)", "不可保存，服务器重启自动重置为0。"],
        G: ["G0-G999 (全局变量，数字型)", "可保存。（存放在Mir200/GlobalVal.ini文件里面）"],
        A: ["A0-A999 (全局变量，字符型)", "可保存。（存放在Mir200/GlobalVal.ini文件里面）"],
        U: ["U0-U499 (私人变量，数字型)", "可保存。（存放在人物数据库Mir.db里面、值最大范围正负21亿）"],
        T: ["T0-T499 (私人变量，字符型)", "可保存。（存放在人物数据库Mir.db里面、字符长度256<1个字母为1字符、1汉字为2字符>）"],
        J: ["J0-J499 (私人变量，数字型)", "可保存,每晚自动12点重置,合区或关停服务器请错开00:00点即可。（存放在人物数据库Mir.db里面、值最大范围正负21亿）"],
        Z: ["Z0-J499 (私人变量，字符型)", "可保存,每晚自动12点重置,合区或关停服务器请错开00:00点即可。（存放在人物数据库Mir.db里面、自定义清理时间位于参数设置 - 时间控制,和J变量共清理时间）"],
    }
    /**
     * 
     * @param {vscode.ExtensionContext} context 
     */
    constructor(context) {
        this._onDidChangeTreeData = new vscode.EventEmitter();
        this.onDidChangeTreeData = this._onDidChangeTreeData.event;
        this.context = context;
        this.matchs()
    }
    matchs() {
        const folderPath = vscode.workspace.workspaceFolders[0].uri.fsPath;
        const dir = 'Mir200/Envir'; // 可以动态传入
        const searchDir = path.join(folderPath, dir)
        this.walk(searchDir, this.rules)
        this.refresh()
    }
    refresh() {
        this._onDidChangeTreeData.fire();
    }
    updateVars(vars) {
        vars.map(name => ({ key: name[0], name })).forEach(({ key, name }) => {
            key = key.toUpperCase()
            name = name.toUpperCase()
            if (!this.vars[key]) {
                this.vars[key] = []
            }
            if (!this.vars[key].includes(name)) {
                this.vars[key].push(name)
            }
        })
    }

    getChildren(element) {
        if (!element) {
            const keys = Object.keys(this.vars)
            const sort = keys.sort((a, b) => a.localeCompare(b));
            return sort.map(key => {
                return new VarsTreeItem({ key, label: this.labels[key][0], tooltip: this.labels[key][1] }, vscode.TreeItemCollapsibleState.Collapsed)
            })
        }
        const sort = this.vars[element.key].sort((a, b) => {
            const an = parseInt(a.replace(/^[A-Z](\d+)$/, "$1"))
            const bn = parseInt(b.replace(/^[A-Z](\d+)$/, "$1"))
            return an - bn
        })
        return sort.map(name => new VarsTreeItem({ label: name, tooltip: "" }))
    }

    getTreeItem(element) {
        return element;
    }
    /**
     * 
     * @param {string} currentPath 
     * @param {RegExp[]} regExpArray 
     * @returns 
     */
    walk(currentPath, regExpArray) {
        const files = fs.readdirSync(currentPath);
        files.forEach(file => {
            const fullPath = path.join(currentPath, file);
            const stat = fs.statSync(fullPath);
            if (stat.isDirectory()) {
                this.walk(fullPath, regExpArray);
            } else if (fullPath.endsWith('.txt')) {
                const content = iconv.decode(fs.readFileSync(fullPath), 'gbk')
                const list = regExpArray.map(regExp => content.match(regExp)).filter(v => !!v);
                if (list && list.length) {
                    this.updateVars(list.flat())
                }
            }
        });
        return true;
    }

    /**
     * 
     * @param {vscode.ExtensionContext} context 
     */
    static init(context) {
        const provider = new VarsUsedTreeViewProvider(context);
        context.subscriptions.push(
            vscode.window.registerTreeDataProvider("mir_script_activity_variable", provider),
        );
    }
}

module.exports = { VarsUsedTreeViewProvider }